package net.oschina.j2cache.util;

import net.oschina.j2cache.CacheException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Properties;

/**
 * 对象序列化工具包
 *
 * @author Winter Lau(javayou@gmail.com)
 */
public class SerializationUtils {

  private static final Logger log = LoggerFactory.getLogger(SerializationUtils.class);
  private static Serializer g_serializer;

  /**
   * 初始化序列化器
   *
   * @param ser serialization method
   * @param props serializer properties
   */
  public static void init(String ser, Properties props) {
    if (ser == null || "".equals(ser.trim())) {
      g_serializer = new JavaSerializer();
    } else {
      switch (ser) {
        case "java":
          g_serializer = new JavaSerializer();
          break;
        case "fst":
          g_serializer = new FSTSerializer();
          break;
        case "kryo":
          g_serializer = new KryoSerializer();
          break;
        case "kryo-pool":
          g_serializer = new KryoPoolSerializer();
          break;
        case "fst-snappy":
          g_serializer = new FstSnappySerializer();
          break;
        case "json":
          g_serializer = new FstJSONSerializer(props);
          break;
        case "fastjson":
          g_serializer = new FastjsonSerializer();
          break;
        case "fse":
          g_serializer = new FseSerializer();
          break;
        default:
          try {
            g_serializer = (Serializer) Class.forName(ser).newInstance();
          } catch (Exception e) {
            throw new CacheException("Cannot initialize Serializer named [" + ser + ']', e);
          }
          break;
      }
    }
    log.info("Using Serializer -> [{}:{}]", g_serializer.name(), g_serializer.getClass().getName());
  }

  public static byte[] serializeWithoutException(Object obj) {
    try {
      return serialize(obj);
    } catch (IOException e) {
      throw new CacheException(e);
    }
  }

  /**
   * 针对不同类型做单独处理
   *
   * @param obj 待序列化的对象
   * @return 返回序列化后的字节数组
   * @throws IOException io exception
   */
  public static byte[] serialize(Object obj) throws IOException {
    if (obj == null) {
      return null;
    }
    return g_serializer.serialize(obj);
  }

  /**
   * 反序列化
   *
   * @param bytes 待反序列化的字节数组
   * @return 序列化后的对象
   * @throws IOException io exception
   */
  public static Object deserialize(byte[] bytes) throws IOException {
    if (bytes == null || bytes.length == 0) {
      return null;
    }
    return g_serializer.deserialize(bytes);
  }
}
